﻿using GameBoard;
using HelixToolkit.Wpf;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;

namespace CombatObjectWrapper
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class COWWindow : Window
    {
        private static String _fileOpenFilter = "All Object Types|*.3ds;*.lwo;*.obj;*.objz;*.stl;*.off|" +
                 "3ds|*.3ds|lwo|*.lwo|objz|*.objz|stl|*.stl|off|*.off";
        private static String _fileSaveFilter = "cobj files (*.cobj)|*.cobj";
        private static String _imageFilter = "All Graphics Types|*.bmp;*.jpg;*.jpeg;*.png;*.tif;*.tiff|" +
                         "BMP|*.bmp|GIF|*.gif|JPG|*.jpg;*.jpeg|PNG|*.png|TIFF|*.tif;*.tiff";
        ModelVisual3D _samplePerson;
        CombatObjectViewModel _viewModel;
        GameBoardVisual _viewport = new GameBoardVisual(BoardsViewModel.BoardTypes.Main);
        public COWWindow()
        {
            InitializeComponent();
            GameVisual_DockPanel.Children.Add(_viewport);
             _viewModel = new CombatObjectViewModel(_viewport);
            DataContext = _viewModel;
            _viewport.LockRotation = false;
            var pictureDir = Directory.GetCurrentDirectory()+"\\"+GameboardConstants.PiecePictureDirectory;
            var mapDir = Directory.GetCurrentDirectory()+"\\MapPictures\\";
            
            VisualsViewModel.Instance.RegisterGameBoardVisual(_viewport);
            var firstMap = Directory.GetFiles(mapDir, "*.*", SearchOption.AllDirectories).FirstOrDefault();
            var firstPicture = Directory.GetFiles(pictureDir).FirstOrDefault();
            if (firstMap != null)
            {
                VisualsViewModel.Instance.SetBoardBackground(firstMap, 100, 100, 0, true);
            }
            if(firstPicture!=null)
            {
                var onlyPieceID = Guid.NewGuid();
                VisualsViewModel.Instance.AddImagePieceToMap(firstPicture, Colors.Red, "Placeholder", 5,
                    new Point3D(), new List<StatusEffectDisplay>(), 30, onlyPieceID,
                    new List<int>() {1,2,4 });
                VisualsViewModel.Instance.SetActive(onlyPieceID);
                VisualsService.BoardsViewModel.ZoomTo(new List<Guid>(){onlyPieceID}, 
                    BoardsViewModel.BoardTypes.All);
            }
        }

        private void Read_Button_Click(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Directory.GetCurrentDirectory() + "\\3DObjects\\ObjectFiles";
            openFileDialog.Filter = _fileOpenFilter;
            if ((bool)openFileDialog.ShowDialog())
            {
                try
                {
                    var targetObjFile = openFileDialog.FileName;
                    _viewModel.ModelObjectFile = openFileDialog.FileName;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }

        private ModelVisual3D MakeModelVisual3DFromObjectFile(string modelPath, Material frontMaterial)
        {
            var objReader = new ObjReader();
            var group = objReader.Read(modelPath);
            ModelVisual3D myModelVisual3D = new ModelVisual3D();
            myModelVisual3D.Content = group;
            string materialFile = modelPath.Replace(".obj", ".mtl");
            if (!File.Exists(materialFile))
            {
                foreach (GeometryModel3D geometry in (myModelVisual3D.Content as Model3DGroup).Children)
                {
                        geometry.Material = frontMaterial;
                }
            }

            return myModelVisual3D;
        }

        private void MaterialButton_Click(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Directory.GetCurrentDirectory() + "\\3DObjects\\ObjectVisuals";
            openFileDialog.Filter = _imageFilter;
            if ((bool)openFileDialog.ShowDialog())
            {
                try
                {
                    var targetMaterialFile = openFileDialog.FileName;
                    if (String.IsNullOrWhiteSpace(_viewModel.ModelObjectFile))
                        return;
                    _viewModel.MaterialFile = targetMaterialFile;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }

        private void SaveObject_Button_Click(object sender, RoutedEventArgs e)
        {
            var saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = _fileSaveFilter;
            saveFileDialog1.InitialDirectory = Directory.GetCurrentDirectory() + "\\3DObjects";
            saveFileDialog1.Title = "Save the current combat object file";
            saveFileDialog1.ShowDialog();

            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {
                SaveObject(saveFileDialog1.FileName);
            }
        }
        private void SaveObject(String fileName)
        {
            WriteToXML(_viewModel.CurrentData, fileName, typeof(ObjectVisualData));
        }
        private void WriteToXML(Object someObject, String fileName, Type theType)
        {
            var settings = new XmlWriterSettings { Indent = true };
            var ser = new DataContractSerializer(theType, null, int.MaxValue, false, true, null);
            using (XmlWriter w = XmlWriter.Create(fileName, settings))
                ser.WriteObject(w, someObject);
        }



        private void LoadObject_Button_Click(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Directory.GetCurrentDirectory() + "\\3DObjects";
            openFileDialog.Filter = _fileSaveFilter;
            if ((bool)openFileDialog.ShowDialog())
            {
                try
                {
                    var readObj = ReadFromXML(openFileDialog.FileName, typeof(ObjectVisualData)) as ObjectVisualData;
                    if (readObj != null)
                    {
                        _viewModel.ModelObjectFile = readObj.ObjectFile;
                        if (readObj.MaterialColor!=null)
                        {
                            _viewModel.ColorChosen = readObj.MaterialColor;
                        }
                        if (!String.IsNullOrWhiteSpace(readObj.MaterialFile))
                        {
                            _viewModel.MaterialFile = readObj.MaterialFile;
                        }

                        _viewModel.RotationValue = readObj.Angle;
                        _viewModel.ScaleValue = readObj.Scale;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }

        }
        private Object ReadFromXML(string p0, Type theType)
        {
            using (var reader = new FileStream(p0, FileMode.Open, FileAccess.Read))
            {
                var ser = new DataContractSerializer(theType);
                return ser.ReadObject(reader);
            }
        }

        private void Color_Button_Click(object sender, RoutedEventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            colorDialog.Owner = this;
            colorDialog.ShowDialog();
            //if ((bool)colorDialog.ShowDialog())
            //{
                _viewModel.ColorChosen = colorDialog.SelectedColor;
            //}
        }
    }
}

